using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Shapes;
using WPFTemplateLib.WpfHelpers;
using Point = System.Drawing.Point;

namespace WPFPractice.UserControls.DynamicColumnTable
{
	/// <summary>
	/// 动态列表格
	/// 已知问题：不能放在 Orientation="Horizontal" 的 StackPanel 等容器中，会导致单元格宽度与列表头不一致。解决方法：可放在 WrapPanel、Grid 等容器中。
	/// </summary>
	public partial class DynamicColumnTable : UserControl
	{
		#region 依赖属性

		/// <summary>
		/// 数据
		/// </summary>
		public DataTable DataTable
		{
			get => (DataTable)GetValue(DataTableProperty);
			set => SetValue(DataTableProperty, value);
		}
		public static readonly DependencyProperty DataTableProperty =
			DependencyProperty.Register(nameof(DataTable), typeof(DataTable), typeof(DynamicColumnTable), new PropertyMetadata(new DataTable(), DataTableChangedCallback));

		/// <summary>
		/// 数据变动回调
		/// </summary>
		private static void DataTableChangedCallback(DependencyObject d, DependencyPropertyChangedEventArgs e)
		{
			DynamicColumnTable dynamicColumnTable = (DynamicColumnTable)d;

			if(e.OldValue is DataTable dt)
			{
				dt.Rows.CollectionChanged -= dynamicColumnTable.Rows_CollectionChanged;
			}

			if(e.NewValue is DataTable dataTable)
			{
				//bool isAutoSetCellPositionValue = ((AutoColTable)d).IsAutoSetCellPositionValue;
				//if (isAutoSetCellPositionValue)
				//{
				dataTable.Rows.CollectionChanged -= dynamicColumnTable.Rows_CollectionChanged;
				dataTable.Rows.CollectionChanged += dynamicColumnTable.Rows_CollectionChanged;
				//}
				//else
				//{
				//    dataTable.Rows.CollectionChanged -= Rows_CollectionChanged;
				//}

				dynamicColumnTable.Rows_CollectionChanged(dynamicColumnTable.DataTable.Rows, null);
			}
		}

		/// <summary>
		/// 列标题高度
		/// </summary>
		public GridLength ColumnHeaderHeight
		{
			get => (GridLength)GetValue(ColumnHeaderHeightProperty);
			set => SetValue(ColumnHeaderHeightProperty, value);
		}
		public static readonly DependencyProperty ColumnHeaderHeightProperty =
			DependencyProperty.Register(nameof(ColumnHeaderHeight), typeof(GridLength), typeof(DynamicColumnTable), new PropertyMetadata(new GridLength(100)));

		/// <summary>
		/// 列宽
		/// </summary>
		public double? ColumnWidth
		{
			get => (double?)GetValue(ColumnWidthProperty);
			set => SetValue(ColumnWidthProperty, value);
		}
		public static readonly DependencyProperty ColumnWidthProperty =
			DependencyProperty.Register(nameof(ColumnWidth), typeof(double?), typeof(DynamicColumnTable), new PropertyMetadata(null));

		#region [依赖属性] 最大单元格宽度
		/// <summary>
		/// [依赖属性] 最大单元格宽度
		/// </summary>
		public double? MaxCellWidth
		{
			get => (double?)GetValue(MaxCellWidthProperty);
			set => SetValue(MaxCellWidthProperty, value);
		}
		public static readonly DependencyProperty MaxCellWidthProperty =
			DependencyProperty.Register(nameof(MaxCellWidth), typeof(double?), typeof(DynamicColumnTable), new PropertyMetadata(null));
		#endregion

		/// <summary>
		/// 行标题宽度
		/// </summary>
		public GridLength RowHeaderWidth
		{
			get => (GridLength)GetValue(RowHeaderWidthProperty);
			set => SetValue(RowHeaderWidthProperty, value);
		}
		public static readonly DependencyProperty RowHeaderWidthProperty =
			DependencyProperty.Register(nameof(RowHeaderWidth), typeof(GridLength), typeof(DynamicColumnTable), new PropertyMetadata(new GridLength(100)));

		/// <summary>
		/// 行高
		/// </summary>
		public double RowHeight
		{
			get => (double)GetValue(RowHeightProperty);
			set => SetValue(RowHeightProperty, value);
		}
		public static readonly DependencyProperty RowHeightProperty =
			DependencyProperty.Register(nameof(RowHeight), typeof(double), typeof(DynamicColumnTable), new PropertyMetadata((double)40));

		/// <summary>
		/// 列标题BorderBrush
		/// </summary>
		public Brush ColHeaderBorderBrush
		{
			get => (Brush)GetValue(ColHeaderBorderBrushProperty);
			set => SetValue(ColHeaderBorderBrushProperty, value);
		}
		public static readonly DependencyProperty ColHeaderBorderBrushProperty =
			DependencyProperty.Register(nameof(ColHeaderBorderBrush), typeof(Brush), typeof(DynamicColumnTable),
				new PropertyMetadata(new SolidColorBrush()));

		/// <summary>
		/// 行标题BorderBrush
		/// </summary>
		public Brush RowHeaderBorderBrush
		{
			get => (Brush)GetValue(RowHeaderBorderBrushProperty);
			set => SetValue(RowHeaderBorderBrushProperty, value);
		}
		public static readonly DependencyProperty RowHeaderBorderBrushProperty =
			DependencyProperty.Register(nameof(RowHeaderBorderBrush), typeof(Brush), typeof(DynamicColumnTable),
				new PropertyMetadata(new SolidColorBrush()));

		/// <summary>
		/// 列标题BorderThickness
		/// </summary>
		public Thickness ColHeaderBorderThickness
		{
			get => (Thickness)GetValue(ColHeaderBorderThicknessProperty);
			set => SetValue(ColHeaderBorderThicknessProperty, value);
		}
		public static readonly DependencyProperty ColHeaderBorderThicknessProperty =
			DependencyProperty.Register(nameof(ColHeaderBorderThickness), typeof(Thickness), typeof(DynamicColumnTable),
				new PropertyMetadata(new Thickness()));

		/// <summary>
		/// 行标题BorderThickness
		/// </summary>
		public Thickness RowHeaderBorderThickness
		{
			get => (Thickness)GetValue(RowHeaderBorderThicknessProperty);
			set => SetValue(RowHeaderBorderThicknessProperty, value);
		}
		public static readonly DependencyProperty RowHeaderBorderThicknessProperty =
			DependencyProperty.Register(nameof(RowHeaderBorderThickness), typeof(Thickness), typeof(DynamicColumnTable),
				new PropertyMetadata(new Thickness()));

		#region [依赖属性] 列标题元素背景色
		/// <summary>
		/// [依赖属性] 列标题元素背景色
		/// </summary>
		public Brush ColHeaderBackground
		{
			get => (Brush)GetValue(ColHeaderBackgroundProperty);
			set => SetValue(ColHeaderBackgroundProperty, value);
		}
		public static readonly DependencyProperty ColHeaderBackgroundProperty =
			DependencyProperty.Register(nameof(ColHeaderBackground), typeof(Brush), typeof(DynamicColumnTable), new PropertyMetadata(new SolidColorBrush()));
		#endregion

		#region [依赖属性] 行标题元素背景色
		/// <summary>
		/// [依赖属性] 行标题元素背景色
		/// </summary>
		public Brush RowHeaderBackground
		{
			get => (Brush)GetValue(RowHeaderBackgroundProperty);
			set => SetValue(RowHeaderBackgroundProperty, value);
		}
		public static readonly DependencyProperty RowHeaderBackgroundProperty =
			DependencyProperty.Register(nameof(RowHeaderBackground), typeof(Brush), typeof(DynamicColumnTable), new PropertyMetadata(new SolidColorBrush()));
		#endregion

		/// <summary>
		/// 是否显示鼠标选择范围
		/// </summary>
		public bool IsShowMouseSelectRange
		{
			get => (bool)GetValue(IsShowMouseSelectRangeProperty);
			set => SetValue(IsShowMouseSelectRangeProperty, value);
		}
		public static readonly DependencyProperty IsShowMouseSelectRangeProperty =
			DependencyProperty.Register(nameof(IsShowMouseSelectRange), typeof(bool), typeof(DynamicColumnTable), new PropertyMetadata(false));

		/// <summary>
		/// [依赖属性]是否显示行勾选框
		/// </summary>
		public bool IsShowRowSelect
		{
			get => (bool)GetValue(IsShowRowSelectProperty);
			set => SetValue(IsShowRowSelectProperty, value);
		}
		public static readonly DependencyProperty IsShowRowSelectProperty =
			DependencyProperty.Register(nameof(IsShowRowSelect), typeof(bool), typeof(DynamicColumnTable), new PropertyMetadata(false));

		/// <summary>
		/// [依赖属性]是否显示列勾选框
		/// </summary>
		public bool IsShowColumnSelect
		{
			get => (bool)GetValue(IsShowColumnSelectProperty);
			set => SetValue(IsShowColumnSelectProperty, value);
		}
		public static readonly DependencyProperty IsShowColumnSelectProperty =
			DependencyProperty.Register(nameof(IsShowColumnSelect), typeof(bool), typeof(DynamicColumnTable), new PropertyMetadata(false));

		/// <summary>
		/// [依赖属性]是否相同内容相同颜色
		/// </summary>
		public bool IsSameColorForSameContent
		{
			get => (bool)GetValue(IsSameColorForSameContentProperty);
			set => SetValue(IsSameColorForSameContentProperty, value);
		}
		public static readonly DependencyProperty IsSameColorForSameContentProperty =
			DependencyProperty.Register(nameof(IsSameColorForSameContent), typeof(bool), typeof(DynamicColumnTable), new PropertyMetadata(false));

		/// <summary>
		/// [依赖属性]是否自动计算单元格坐标
		/// </summary>
		public bool IsAutoSetCellPositionValue
		{
			get => (bool)GetValue(IsAutoSetCellPositionValueProperty);
			set => SetValue(IsAutoSetCellPositionValueProperty, value);
		}
		public static readonly DependencyProperty IsAutoSetCellPositionValueProperty =
			DependencyProperty.Register(nameof(IsAutoSetCellPositionValue), typeof(bool), typeof(DynamicColumnTable), new PropertyMetadata(false));

		/// <summary>
		/// [依赖属性]是否显示 ToolTip
		/// </summary>
		public bool IsShowTip
		{
			get => (bool)GetValue(IsShowTipProperty);
			set => SetValue(IsShowTipProperty, value);
		}
		public static readonly DependencyProperty IsShowTipProperty =
			DependencyProperty.Register(nameof(IsShowTip), typeof(bool), typeof(DynamicColumnTable), new PropertyMetadata(false));

		/// <summary>
		/// [依赖属性]是否可编辑
		/// </summary>
		public bool CanEdit
		{
			get => (bool)GetValue(CanEditProperty);
			set => SetValue(CanEditProperty, value);
		}
		public static readonly DependencyProperty CanEditProperty =
			DependencyProperty.Register(nameof(CanEdit), typeof(bool), typeof(DynamicColumnTable), new PropertyMetadata(true));

		#region [依赖属性] 是否显示行标题
		/// <summary>
		/// [依赖属性] 是否显示行标题
		/// </summary>
		public bool IsShowRowHeader
		{
			get => (bool)GetValue(IsShowRowHeaderProperty);
			set => SetValue(IsShowRowHeaderProperty, value);
		}
		public static readonly DependencyProperty IsShowRowHeaderProperty =
			DependencyProperty.Register(nameof(IsShowRowHeader), typeof(bool), typeof(DynamicColumnTable), new PropertyMetadata(true));
		#endregion

		#region [依赖属性] 是否显示列标题
		/// <summary>
		/// [依赖属性] 是否显示列标题
		/// </summary>
		public bool IsShowColumnHeader
		{
			get => (bool)GetValue(IsShowColumnHeaderProperty);
			set => SetValue(IsShowColumnHeaderProperty, value);
		}
		public static readonly DependencyProperty IsShowColumnHeaderProperty =
			DependencyProperty.Register(nameof(IsShowColumnHeader), typeof(bool), typeof(DynamicColumnTable), new PropertyMetadata(true));
		#endregion

		#endregion

		#region 路由事件

		public static readonly RoutedEvent RangeSelectedEvent = EventManager.RegisterRoutedEvent("RangeSelected",
			RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(DynamicColumnTable));
		/// <summary>
		/// [路由事件]范围选择完成（事件参数的 OriginalSource 属性存放了 BatchSetTextBoxMessage 对象）
		/// </summary>
		public event RoutedEventHandler RangeSelected
		{
			add => AddHandler(RangeSelectedEvent, value);
			remove => RemoveHandler(RangeSelectedEvent, value);
		}
		/// <summary>
		/// 路由事件 范围选择完成 的触发方法
		/// </summary>
		/// <param name="originalSource">此参数会传递到事件参数的 OriginalSource 属性中</param>
		private void RaiseRangeSelectedEvent(object originalSource = null)
		{
			RaiseEvent(new RoutedEventArgs(RangeSelectedEvent, originalSource));
		}

		#endregion

		#region 命令

		public RelayCommand<object[]> ParamSelectsCommand { get; }
		public RelayCommand<object[]> ParamNumberCommand { get; }
		public RelayCommand<TableCell> CellClickCommand { get; }

		#endregion

		#region 成员

		public DynamicColumnTable()
		{
			InitializeComponent();

			ParamSelectsCommand = new RelayCommand<object[]>(OnParamSelectsCommand);
			ParamNumberCommand = new RelayCommand<object[]>(OnParamNumberCommand);
			CellClickCommand = new RelayCommand<TableCell>(OnCellClickCommand);
		}

		/// <summary>
		/// 范围选择时的起始位置
		/// </summary>
		private Point _beginPosition;

		/// <summary>
		/// 原先的横向滚动偏移
		/// </summary>
		double _originScrollH;
		/// <summary>
		/// 原先的纵向滚动偏移
		/// </summary>
		double _originScrollV;

		#endregion

		#region 方法

		/// <summary>
		/// 行集合变化
		/// </summary>
		private void Rows_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
		{
			var rows = sender as ObservableCollection<TableRow>;
			if(rows == null)
				return;

			if(IsAutoSetCellPositionValue)
			{
				var rowList = rows.ToList();
				for(var i = 0; i < rowList.Count; i++)
				{
					var colList = rowList[i].Cells.ToList();
					for(int j = 0; j < colList.Count; j++)
					{
						colList[j].Position = new Point(i, j);
					}
				}
			}

			if(IsSameColorForSameContent)
			{
				CheckAndFillCellsBackground(rows.ToList());
			}
		}

		/// <summary>
		/// 检查并填充单元格背景
		/// </summary>
		/// <param name="rows">行集合</param>
		private static void CheckAndFillCellsBackground(List<TableRow> rows)
		{
			var cells = rows.SelectMany(x => x.Cells).Where(x => x.BackgroundColor == TableCell.CellDefaultColor)
				.ToList();
			foreach(var cell in cells)
			{
				ChangeCellBackgroundColor(rows, cell);
			}
		}

		private void OnParamSelectsCommand(object[] obj)
		{
			try
			{
				var value = obj[0] == null ? new() : obj[0] as KeyValueModel;
				var options = obj[1] as List<KeyValueModel>;

				if(value == null)
				{
					throw new Exception("动态表格单元格类型为string类型时Value需要是KeyValueModel类型.");
				}

				RememberScrollOffset();

				//var dlg = new SelectView();
				//var dc = dlg.DataContext as SelectViewModel;
				//dc.Title = "";
				//dc.ProjectList.Clear();
				//foreach (var option in options)
				//{
				//	var kv = new KeyValueModel
				//	{
				//		Key = option.Key,
				//		Value = option.Value
				//	};

				//	dc.ProjectList.Add(kv);
				//	if (EqualHelper.Equal(value, option))
				//	{
				//		dc.Selected = kv;
				//	}
				//}

				//if (dlg.ShowDialog().Value)
				//{
				//	value.Key = dc.Selected.key;
				//	value.Value = dc.Selected.value;
				//}
			}
			catch(Exception ex)
			{
				MessageBox.Show(ex.Message);
			}
			finally
			{
				RecoverScrollOffset();
			}
		}

		private void OnParamNumberCommand(object[] obj)
		{
			try
			{
				var textBox = obj[0] as TextBox;
				var typeName = (TableCellTypeEnum)obj[1];

				RememberScrollOffset();

				//var dlg = new NumKeyboardView(textBox.Text);
				//if (dlg.ShowDialog().Value)
				//{
				//	if (typeName == TableCellTypeEnum.@int || typeName == TableCellTypeEnum.@double || 
				//		typeName == TableCellTypeEnum.@float)
				//	{
				//		var num = dlg.DoubleValue;
				//		var lower = double.Parse(obj[2].ToString());
				//		var upper = double.Parse(obj[3].ToString());
				//		if (num !=null && !(num >= lower && num <= upper))
				//		{
				//			throw new Exception($"取值需在{lower}-{upper}范围内");
				//		}
				//	}

				//	textBox.Text = dlg.StringValue;
				//	if (dlg.StringValue == "")
				//	{
				//		textBox.Text = null;
				//	}
				//}
			}
			catch(Exception ex)
			{
				MessageBox.Show(ex.Message);
			}
			finally
			{
				RecoverScrollOffset();
			}
		}

		/// <summary>
		/// 调整选取范围表示形式为左上角到右下角
		/// </summary>
		/// <param name="originBeginPosition">原始的开始位置</param>
		/// <param name="originEndPosition">原始的结束位置</param>
		/// <returns>统一的起止位置（左上角到右下角）</returns>
		private (Point beginPosition, Point endPosition) AdjustRangePosition(Point originBeginPosition, Point originEndPosition)
		{
			Point beginPosition = originBeginPosition;
			Point endPosition = originEndPosition;

			//起点在左下角;
			if(beginPosition.X > endPosition.X && beginPosition.Y < endPosition.Y)
			{
				var temp = beginPosition;
				beginPosition = new Point(endPosition.X, beginPosition.Y);
				endPosition = new Point(temp.X, endPosition.Y);
			}

			//起点在右下角;
			if(beginPosition.X >= endPosition.X && beginPosition.Y >= endPosition.Y)
			{
				(beginPosition, endPosition) = (endPosition, beginPosition);
			}

			//起点在右上角;
			if(beginPosition.X < endPosition.X && beginPosition.Y > endPosition.Y)
			{
				var temp = beginPosition;
				beginPosition = new Point(beginPosition.X, endPosition.Y);
				endPosition = new Point(endPosition.X, temp.Y);
			}

			return (beginPosition, endPosition);
		}

		#region 滚动条

		/// <summary>
		/// 记住滚动条位置
		/// </summary>
		private void RememberScrollOffset()
		{
			_originScrollH = cell_scroll.HorizontalOffset;
			_originScrollV = cell_scroll.VerticalOffset;
		}

		/// <summary>
		/// 复原滚动条偏移
		/// </summary>
		private void RecoverScrollOffset()
		{
			cell_scroll.ScrollToHorizontalOffset(_originScrollH);
			cell_scroll.ScrollToVerticalOffset(_originScrollV);
		}

		private void ColHeader_ScrollChanged(object sender, ScrollChangedEventArgs e)
		{
			var sv = e.OriginalSource as ScrollViewer;
			if(sv != null)
			{
				cell_scroll.ScrollToHorizontalOffset(sv.HorizontalOffset);
			}
		}

		private void RowHeader_ScrollChanged(object sender, ScrollChangedEventArgs e)
		{
			var sv = e.OriginalSource as ScrollViewer;
			if(sv != null)
			{
				cell_scroll.ScrollToVerticalOffset(sv.VerticalOffset);
			}
		}

		private void CellPanel_ScrollChanged(object sender, ScrollChangedEventArgs e)
		{
			if(ReferenceEquals(e.OriginalSource, cell_scroll))
			{
				col_header_scroll.ScrollToHorizontalOffset(cell_scroll.HorizontalOffset);
				row_header_scroll.ScrollToVerticalOffset(cell_scroll.VerticalOffset);
			}

			if(e.HorizontalChange != 0)
			{
				RaiseEvent(new ScrolledEventArgs(TableEventHelper.ContentHorizontalScrolledEvent, this) { Direction = Orientation.Horizontal, Offset = e.HorizontalOffset });
			}

			if(e.VerticalChange != 0)
			{
				RaiseEvent(new ScrolledEventArgs(TableEventHelper.ContentVerticalScrolledEvent, this) { Direction = Orientation.Vertical, Offset = e.VerticalOffset });
			}
		}

		/// <summary>
		/// 行集合的 ListBox 滚轮事件处理
		/// </summary>
		private void RowListBox_OnPreviewMouseWheel(object sender, MouseWheelEventArgs e)
		{
			var eventArg = new MouseWheelEventArgs(e.MouseDevice, e.Timestamp, e.Delta)
			{
				RoutedEvent = UIElement.MouseWheelEvent,
				Source = sender
			};

			//将滚轮事件继续外抛，解决 ScrollViewer 内部嵌套的 ListBox 滚动无效的问题
			rowListBox.RaiseEvent(eventArg);
		}

		#endregion

		#region 鼠标选择范围线框（用于 Select 类型）

		/// <summary>
		/// 鼠标是否按下
		/// </summary>
		private bool _isMouseDown = false;

		/// <summary>
		/// 鼠标按下的位置
		/// </summary>
		private System.Windows.Point _mouseDownPosition;

		/// <summary>
		/// 拖动要显示的矩形
		/// </summary>
		private Rectangle _rectangle;

		/// <summary>
		/// 文本框鼠标按下的隧道事件
		/// （拦截鼠标事件、记录起始位置、初始化矩形）
		/// </summary>
		private void TextBox_OnPreviewMouseDown(object sender, MouseButtonEventArgs e)
		{
			e.Handled = true;

			var tb = sender as TextBox;
			if(tb!.DataContext is TableCell cell)
			{
				_beginPosition = cell.Position;
			}

			RememberScrollOffset();

			if(IsShowMouseSelectRange)
			{
				ShowDrag(e, tb);
			}
		}

		/// <summary>
		/// 准备展示拖动
		/// </summary>
		/// <param name="e">鼠标事件</param>
		/// <param name="control">Grid内部对象</param>
		private void ShowDrag(MouseButtonEventArgs e, Control control)
		{
			try
			{
				Grid grid = control.TryFindParent<Grid>();
				if(grid == null)
					return;

				if(_rectangle == null)
				{
					_rectangle = new Rectangle()
					{
						VerticalAlignment = VerticalAlignment.Top,
						HorizontalAlignment = HorizontalAlignment.Left,
						Stroke = new SolidColorBrush(Colors.Coral),
					};
					grid.Children.Add(_rectangle);
					grid.InvalidateArrange(); //更新布局，否则矩形不会盖在上面；

					//_rectangle = grid.FindChild<Rectangle>("rect");
					//if (_rectangle == null)
					//{
					//    return;
					//}
				}

				_isMouseDown = true;
				_mouseDownPosition = e.GetPosition(grid);

				//边距加 1 是为了不让线框和鼠标挨着，避免影响后续事件；
				_rectangle.Margin = new Thickness(_mouseDownPosition.X + 1, _mouseDownPosition.Y + 1, 0, 0);
				_rectangle.Width = 5;
				_rectangle.Height = 5;
				_rectangle.Visibility = Visibility.Visible;
			}
			catch(Exception ex)
			{
				Console.WriteLine(ex);
			}
		}

		/// <summary>
		/// Grid 中的鼠标移动的隧道事件
		/// （实时改变矩形）
		/// </summary>
		private void Grid_OnPreviewMouseMove(object sender, MouseEventArgs e)
		{
			if(!_isMouseDown)
				return;
			if(!IsShowMouseSelectRange)
				return;

			try
			{
				var grid = sender as Grid;
				if(grid == null)
					return;

				var pos = e.GetPosition(grid);
				double marginX = _mouseDownPosition.X;
				double marginY = _mouseDownPosition.Y;
				double width, height;

				double distanceX = pos.X - _mouseDownPosition.X;
				if(distanceX < 0)
				{
					distanceX = Math.Abs(distanceX);
					marginX = _mouseDownPosition.X - distanceX + 1;
					width = distanceX;
				}
				else
				{
					width = distanceX - 1; //减 1 是为了不让线框和鼠标挨着，避免影响后续事件；
				}

				double distanceY = pos.Y - _mouseDownPosition.Y;
				if(distanceY < 0)
				{
					distanceY = Math.Abs(distanceY);
					marginY = _mouseDownPosition.Y - distanceY + 1;
					height = distanceY;
				}
				else
				{
					height = distanceY - 1; //减 1 是为了不让线框和鼠标挨着，避免影响后续事件；
				}

				_rectangle.Margin = new Thickness(marginX, marginY, 0, 0);
				_rectangle.Width = width > 0 ? width : 0;
				_rectangle.Height = height > 0 ? height : 0;
			}
			catch(Exception ex)
			{
				Console.WriteLine(ex);
			}
		}

		/// <summary>
		/// Grid 中的鼠标抬起隧道事件（隐藏矩形）
		/// </summary>
		private void Grid_OnPreviewMouseUp(object sender, MouseButtonEventArgs e)
		{
			try
			{
				var grid = sender as Grid;
				if(grid == null)
					return;

				_isMouseDown = false;
				if(IsShowMouseSelectRange)
				{
					_rectangle.Visibility = Visibility.Collapsed;
				}
			}
			catch(Exception ex)
			{
				Console.WriteLine(ex);
			}
		}

		#endregion

		/// <summary>
		/// 文本框的鼠标抬起隧道事件
		/// </summary>
		private void TextBox_OnPreviewMouseUp(object sender, MouseButtonEventArgs e)
		{
			var tb = sender as TextBox;
			if(tb == null)
				return;

			TableCell lastCell = tb.DataContext as TableCell;
			if(lastCell == null)
				return;

			var (beginPosition, endPosition) = AdjustRangePosition(_beginPosition, lastCell.Position);

			var message = new BatchSetTextBoxMessage()
			{
				PositionBegin = beginPosition,
				PositionEnd = endPosition,
				Text = tb.Text,
			};

			RaiseRangeSelectedEvent(message);
		}

		/// <summary>
		/// 文本框值改变
		/// </summary>
		private void TextBox_OnTextChanged(object sender, TextChangedEventArgs e)
		{
			var tb = sender as TextBox;
			if(tb == null)
				return;

			//此处使用路由事件的好处就是可灵活放置接收消息的位置；
			tb.RaiseEvent(new RoutedEventArgs(TableEventHelper.CellValueChangedEvent, tb.DataContext));

			RecoverScrollOffset();
		}

		/// <summary>
		/// 单元格值改变
		/// </summary>
		private void OnCellValueChanged(object sender, RoutedEventArgs e)
		{
			if(!IsSameColorForSameContent)
				return;

			var cell = e.OriginalSource as TableCell;
			if(cell == null)
				return;

			ChangeCellBackgroundColor(DataTable.Rows.ToList(), cell);
		}

		/// <summary>
		/// 改变单元格背景颜色
		/// </summary>
		/// <param name="rows">行集合</param>
		/// <param name="cell">单元格对象</param>
		private static void ChangeCellBackgroundColor(List<TableRow> rows, TableCell cell)
		{
			if(string.IsNullOrWhiteSpace(cell.Value + ""))
			{
				cell.BackgroundColor = TableCell.CellDefaultColor;
				return;
			}

			var tableCells = rows.SelectMany(x => x.Cells).ToList();
			var coloredItem = tableCells.FirstOrDefault(x =>
				x != cell && x.Value + "" == cell.Value + "" && x.BackgroundColor != TableCell.CellDefaultColor);

			Color color;
			if(coloredItem != null)
			{
				color = coloredItem.BackgroundColor;
			}
			else
			{
				color = GetRandomColor();
				while(tableCells.Exists(x => x.BackgroundColor == color))
				{
					color = GetRandomColor();
				}
			}

			cell.BackgroundColor = color;
		}

		/// <summary>
		/// 获取随机颜色
		/// </summary>
		/// <returns>System.Windows.Media.Color</returns>
		private static Color GetRandomColor()
		{
			Color color;
#if NET6_0_OR_GREATER
			color = Color.FromRgb((byte)Random.Shared.Next(100, 255), (byte)Random.Shared.Next(100, 255), (byte)Random.Shared.Next(100, 255));
#else
            Random random = new Random();
            color = Color.FromRgb((byte)random.Next(100, 255), (byte)random.Next(100, 255), (byte)random.Next(100, 255));
#endif
			return color;
		}

		private void OnCellClickCommand(TableCell cell)
		{
			if(cell.ClickCallback != null)
			{
				try
				{
					RememberScrollOffset();

					cell.ClickCallback(cell);
				}
				catch(Exception ex)
				{
					Console.WriteLine(ex);
					MessageBox.Show(ex.Message);
				}
				finally
				{
					RecoverScrollOffset();
				}
			}
		}

		#endregion

		/// <summary>
		/// 列标题勾选状态改变事件
		/// </summary>
		private void ColChecker_CheckStatusChanged(object sender, RoutedEventArgs e)
		{
			CheckBox cb = sender as CheckBox;
			if(cb == null)
				return;

			RaiseEvent(new CheckChangedEventArgs(TableEventHelper.ColumnHeaderCheckChangedEvent, cb)
			{
				Tag = cb.Tag + "",
				IsChecked = cb.IsChecked ?? false,
			});
		}

		/// <summary>
		/// 行标题勾选状态改变事件
		/// </summary>
		/// <exception cref="NotImplementedException"></exception>
		private void RowChecker_CheckStatusChanged(object sender, RoutedEventArgs e)
		{
			CheckBox cb = sender as CheckBox;
			if(cb == null)
				return;

			RaiseEvent(new CheckChangedEventArgs(TableEventHelper.RowHeaderCheckChangedEvent, cb)
			{
				Tag = cb.Tag + "",
				IsChecked = cb.IsChecked ?? false,
			});
		}
	}
}
